﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HCSAnalyzer.Forms.FormsForImages;
using System.Drawing;
using HCSAnalyzer.Classes;
using HCSAnalyzer.Classes.Base_Classes.DataStructures;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using HCSAnalyzer.Classes.Base_Classes.DataAnalysis;
using HCSAnalyzer.Classes.Base_Classes.Viewers;
using HCSAnalyzer.Classes.Base_Classes.DataProcessing;
using HCSAnalyzer.Classes.MetaComponents;
using HCSAnalyzer;
using Kitware.VTK;
using HCSAnalyzer.Classes.ImageAnalysis._3D_Engine;
using HCSAnalyzer.Classes._3D;
using System.IO;

namespace ImageAnalysis
{
    public partial class cImage : IDisposable
    {
        public cListSingleChannelImage SingleChannelImage = new cListSingleChannelImage();
        //  public float[][] Data {get; private set;}
        public int Width { get; private set; }
        public int Height { get; private set; }
        public int Depth { get; private set; }

        public void Dispose()
        {
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue 
            // and prevent finalization code for this object
            // from executing a second time.
            SingleChannelImage.Dispose();
            GC.SuppressFinalize(this);
            GC.Collect();
        }




        public int GetNumChannels()
        {
            return this.SingleChannelImage.Count;
        }

        public int SliceSize { get; private set; }
        public int ImageSize { get; private set; }
        public string Name = "New Image";
        public object Tag;
        public double XResolution = 1;
        public double YResolution = 1;
        public double ZResolution = 1;


        /// <summary>
        /// Build a BITMAP from a cImage
        /// </summary>
        /// <param name="ZoomFactor"></param>
        /// <param name="ListMin">Minimum values for each band (if NULL then automatically computed)</param>
        /// <param name="ListMax">Maximum values for each band (if NULL then automatically computed)</param>
        /// <param name="ListLUTs">use  cLUT ListLUT = new cLUT() to build your LUT</param>
        /// <returns></returns>
        public Bitmap GetBitmap(float ZoomFactor, List<double> ListMin, List<double> ListMax, List<byte[][]> ListLUTs)
        {
            if (ListMax == null)
            {
                ListMax = new List<double>();
                for (int i = 0; i < this.GetNumChannels(); i++)
                {
                    this.SingleChannelImage[i].UpDateMax();
                    ListMax.Add(this.SingleChannelImage[i].Max);
                }
            }
            if (ListMin == null)
            {
                ListMin = new List<double>();
                for (int i = 0; i < this.GetNumChannels(); i++)
                {
                    this.SingleChannelImage[i].UpDateMin();
                    ListMin.Add(this.SingleChannelImage[i].Min);
                }
            }

            int NewWidth = (int)(this.Width * ZoomFactor);
            int NewHeight = (int)(this.Height * ZoomFactor);

            Bitmap BMPToBeReturned = new Bitmap(NewWidth, NewHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            // Lock the bitmap's bits.  
            Rectangle rect = new Rectangle(0, 0, NewWidth, NewHeight);
            System.Drawing.Imaging.BitmapData bmpData = BMPToBeReturned.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, BMPToBeReturned.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            int scanline = Math.Abs(bmpData.Stride);

            int bytes = scanline * NewHeight;
            byte[] rgbValues = new byte[bytes];

            byte CurrentRed;
            byte CurrentGreen;
            byte CurrentBlue;

            int RealX;
            int RealY;

            // Copy the RGB values into the array.
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

            for (int IdxChannel = 0; IdxChannel < this.GetNumChannels(); IdxChannel++)
            {
                byte[][] CurrentLUT = ListLUTs[IdxChannel];

                for (int FullY = 0; FullY < NewHeight; FullY++)
                {
                    RealY = (int)(FullY / ZoomFactor);
                    if (RealY >= this.Height) RealY = this.Height - 1;

                    for (int FullX = 0; FullX < NewWidth; FullX++)
                    {
                        RealX = (int)(FullX / ZoomFactor);
                        if (RealX >= this.Width) RealX = this.Width - 1;

                        float Value = this.SingleChannelImage[IdxChannel].Data[RealX + RealY * this.Width];

                        int ConvertedValue = (int)((((CurrentLUT[0].Length - 1) * (Value - ListMin[IdxChannel]))
                                                    / (ListMax[IdxChannel] - ListMin[IdxChannel])));

                        if (ConvertedValue < 0) ConvertedValue = 0;
                        if (ConvertedValue >= CurrentLUT[0].Length) ConvertedValue = CurrentLUT[0].Length - 1;

                        CurrentRed = (byte)CurrentLUT[0][ConvertedValue];
                        CurrentGreen = (byte)CurrentLUT[1][ConvertedValue];
                        CurrentBlue = (byte)CurrentLUT[2][ConvertedValue];

                        double NewValue = rgbValues[3 * FullX + FullY * scanline] + CurrentBlue;
                        if (NewValue > 255)
                            rgbValues[3 * FullX + FullY * scanline] = 255;
                        else
                            rgbValues[3 * FullX + FullY * scanline] += CurrentBlue;

                        NewValue = rgbValues[3 * FullX + 1 + FullY * scanline] + CurrentGreen;
                        if (NewValue > 255)
                            rgbValues[3 * FullX + 1 + FullY * scanline] = 255;
                        else
                            rgbValues[3 * FullX + 1 + FullY * scanline] += CurrentGreen;

                        NewValue = rgbValues[3 * FullX + 2 + FullY * scanline] + CurrentRed;
                        if (NewValue > 255)
                            rgbValues[3 * FullX + 2 + FullY * scanline] = 255;
                        else
                            rgbValues[3 * FullX + 2 + FullY * scanline] += CurrentRed;
                    }
                }
            }

            // Copy the RGB values back to the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

            // Unlock the bits.
            BMPToBeReturned.UnlockBits(bmpData);

            return BMPToBeReturned;
        }

        #region Constructors
        private cImage()
        {
            SliceSize = this.Width * this.Height;
            ImageSize = SliceSize * Depth;
            UpDateName();
        }

        public cImage(int Width, int Height, int Depth, int NumChannels)
        {
            //this.NumChannels = NumChannels;
            this.Width = Width;
            this.Height = Height;
            this.Depth = Depth;
            this.SliceSize = this.Height * this.Width;
            this.ImageSize = SliceSize * Depth;
            this.SingleChannelImage = new cListSingleChannelImage();

            for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
            {
                this.SingleChannelImage.Add(new cSingleChannelImage(Width, Height, Depth, new cPoint3D(1,1,1)));
                this.SingleChannelImage[this.SingleChannelImage.Count - 1].Name = "Channel " + IdxChannel;
            }
            UpDateName();
        }

        public cImage(Image<Gray, float> CVImage)
        {
            //this.output = new cImage(this.input);
            this.Width = CVImage.Width;
            this.Height = CVImage.Height;
            this.SliceSize = this.Height * this.Width;
            this.ImageSize = SliceSize * Depth;

            this.SingleChannelImage = new cListSingleChannelImage();
            //for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
            this.SingleChannelImage.Add(new cSingleChannelImage(Width, Height, 1, new cPoint3D(1, 1, 1)));

            for (int j = 0; j < CVImage.Height; j++)
                for (int i = 0; i < CVImage.Width; i++)
                    this.SingleChannelImage[0].Data[i + j * this.Width] = CVImage.Data[j, i, 0];

            // this.NumChannels = 1;
            UpDateName();
        }

        public cImage(Image<Gray, byte> CVImage)
        {
            //this.output = new cImage(this.input);
            this.Width = CVImage.Width;
            this.Height = CVImage.Height;
            this.SliceSize = this.Height * this.Width;
            this.ImageSize = SliceSize * Depth;

            this.SingleChannelImage = new cListSingleChannelImage();
            //for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
            this.SingleChannelImage.Add(new cSingleChannelImage(Width, Height, 1, new cPoint3D(1, 1, 1)));

            for (int j = 0; j < CVImage.Height; j++)
                for (int i = 0; i < CVImage.Width; i++)
                    this.SingleChannelImage[0].Data[i + j * this.Width] = CVImage.Data[j, i, 0];

            //this.NumChannels = 1;
            UpDateName();
        }

        public cImage(cImage Source)
        {
            //Source.GetNumChannels();
            this.Width = Source.Width;
            this.Height = Source.Height;
            this.Depth = Source.Depth;
            this.SliceSize = this.Height * this.Width;
            this.ImageSize = SliceSize * Depth;

            this.SingleChannelImage = new cListSingleChannelImage();
            for (int IdxChannel = 0; IdxChannel < Source.GetNumChannels(); IdxChannel++)
            {
                this.SingleChannelImage.Add(new cSingleChannelImage(Source.Width, Source.Height, Source.Depth, new cPoint3D(Source.XResolution, Source.YResolution, Source.ZResolution)));
                this.SingleChannelImage[IdxChannel].Data = new float[Source.SingleChannelImage[IdxChannel].Data.Length];

                Array.Copy(Source.SingleChannelImage[IdxChannel].Data, this.SingleChannelImage[IdxChannel].Data, Source.SingleChannelImage[IdxChannel].Data.Length);
            }
            UpDateName();
        }

        public cImage(cSingleChannelImage Source)
        {
            // this.NumChannels = 1;
            this.Width = Source.Width;
            this.Height = Source.Height;
            this.Depth = Source.Depth;
            this.SliceSize = this.Height * this.Width;
            this.ImageSize = SliceSize * Depth;
            this.SingleChannelImage = new cListSingleChannelImage();

            this.SingleChannelImage.Add(new cSingleChannelImage(Source.Width, Source.Height, Source.Depth, Source.Resolution));
            this.SingleChannelImage[0].Data = new float[Source.Data.Length];

            Array.Copy(Source.Data, this.SingleChannelImage[0].Data, Source.Data.Length);

            this.Name = Source.Name;

            UpDateName();
        }

        public cImage(cListExtendedTable ListSources)
        {
            this.BuildFromListTable(ListSources);
            UpDateName();
        }

        public cImage(cExtendedTable Source)
        {
            this.BuildFromListTable(new cListExtendedTable(Source));
            UpDateName();
        }

        public cImage(OpenFileDialog DRes)
        {
            LoadFromPath(DRes.FileName, DRes.SafeFileName);
            UpDateName();
        }

        public cImage(string Path)
        {
            LoadFromPath(Path, "");
            UpDateName();
        }

        public List<int> GetListChannels()
        {
            List<int> ToBeReturned = new List<int>();

            for (int Band = 0; Band < this.SingleChannelImage.Count; Band++)
                ToBeReturned.Add(Band);

            return ToBeReturned;
        }


        void BuildFromListTable(cListExtendedTable ListSources)
        {
            if (ListSources.Count == 0) return;
            if (ListSources[0].Count == 0) return;
            if (ListSources[0][0].Count == 0) return;

            //this.NumChannels = ListSources.Count;
            this.Width = ListSources[0].Count;
            this.Height = ListSources[0][0].Count;
            this.Depth = 1;
            this.SliceSize = this.Height * this.Width;

            this.SingleChannelImage = new cListSingleChannelImage();
            for (int IdxChannel = 0; IdxChannel < ListSources.Count; IdxChannel++)
            {
                this.SingleChannelImage.Add(new cSingleChannelImage(this.Width, this.Height, 1,new cPoint3D(1,1,1)));

                for (int i = 0; i < this.Width; i++)
                    for (int j = 0; j < this.Height; j++)
                    {
                        this.SingleChannelImage[IdxChannel].Data[i + j * this.Width] = (float)ListSources[IdxChannel][i][j];
                    }
            }
            this.Name = ListSources.Name;
        }

        public void CopyInto(cImage SubImage, int Dest_PosX, int Dest_PosY, int Dest_PosZ, int Dest_Channel)
        {
            if (SubImage.GetNumChannels() > 1) return;

            for (int Z = 0; Z < SubImage.Depth; Z++)
            {
                int OriginalPosZ = Dest_PosZ + Z;
                if ((OriginalPosZ < 0) || (OriginalPosZ > this.Depth - 1)) continue;

                for (int Y = 0; Y < SubImage.Height; Y++)
                {
                    int OriginalPosY = Dest_PosY + Y;
                    if ((OriginalPosY < 0) || (OriginalPosY > this.Height - 1)) continue;

                    for (int X = 0; X < SubImage.Width; X++)
                    {
                        int OriginalPosX = Dest_PosX + X;
                        if ((OriginalPosX < 0) || (OriginalPosX > this.Width - 1)) continue;

                        this.SingleChannelImage[Dest_Channel].Data[OriginalPosX + OriginalPosY * this.Width + OriginalPosZ * this.SliceSize] = SubImage.SingleChannelImage[0].Data[X + Y * SubImage.Width + Z * SubImage.SliceSize];
                    }
                }
            }
        }


        public cImage Crop(cPoint3D StartingPoint, cPoint3D EndingPoint)
        {
            cImage CroppedImage = new cImage((int)(EndingPoint.X - StartingPoint.X + 1),
                                            (int)(EndingPoint.Y - StartingPoint.Y + 1),
                                            (int)(EndingPoint.Z - StartingPoint.Z + 1),
                                            this.GetNumChannels());
            int RealPosZ;
            int RealPosY;
            int RealPosX;

            for (int Channel = 0; Channel < this.GetNumChannels(); Channel++)
            {

                for (int z = (int)StartingPoint.Z; z <= (int)EndingPoint.Z; z++)
                {
                    RealPosZ = (int)(z - StartingPoint.Z);
                    for (int y = (int)StartingPoint.Y; y <= (int)EndingPoint.Y; y++)
                    {
                        RealPosY = (int)(y - StartingPoint.Y);
                        for (int x = (int)StartingPoint.X; x <= (int)EndingPoint.X; x++)
                        {
                            RealPosX = (int)(x - StartingPoint.X);
                            CroppedImage.SingleChannelImage[Channel].Data[RealPosX + RealPosY * CroppedImage.Width + RealPosZ * CroppedImage.SliceSize] =
                               this.SingleChannelImage[Channel].Data[x + y * this.Width + z * this.SliceSize];
                        }
                    }
                }
            }

            return CroppedImage;
        }


        public void AddInto(cImage SubImage, int Dest_PosX, int Dest_PosY, int Dest_PosZ, int Dest_Channel)
        {
            if (SubImage.GetNumChannels() > 1) return;

            for (int Z = 0; Z < SubImage.Depth; Z++)
            {
                int OriginalPosZ = Dest_PosZ + Z;
                if ((OriginalPosZ < 0) || (OriginalPosZ > this.Depth - 1)) continue;

                for (int Y = 0; Y < SubImage.Height; Y++)
                {
                    int OriginalPosY = Dest_PosY + Y;
                    if ((OriginalPosY < 0) || (OriginalPosY > this.Height - 1)) continue;

                    for (int X = 0; X < SubImage.Width; X++)
                    {
                        int OriginalPosX = Dest_PosX + X;
                        if ((OriginalPosX < 0) || (OriginalPosX > this.Width - 1)) continue;

                        this.SingleChannelImage[Dest_Channel].Data[OriginalPosX + OriginalPosY * this.Width + OriginalPosZ * this.SliceSize] += SubImage.SingleChannelImage[0].Data[X + Y * SubImage.Width + Z * SubImage.SliceSize];
                    }
                }
            }
        }


        void UpDateName()
        {
            this.Name += " - [" + this.Width + "x" + this.Height + "x" + this.Depth + "]" + " - " + this.GetNumChannels() + " channels";
        }


        void LoadFromPath(string Path, string FileName)
        {
            if (Path == "")
                FileName = Path;

            string[] ListNames = Path.Split('|');

            int ChannelStart = 0;

            for (int IdxName = 0; IdxName < ListNames.Length; IdxName++)
            {
                string CurrentName = ListNames[IdxName];
                if ((CurrentName == "") || (File.Exists(CurrentName) == false)) continue;

                string[] ListSplits = CurrentName.Split('.');
                string Extension = ListSplits[ListSplits.Length - 1].ToLower();

                byte[] rgbValues = null;

                int NumBytePerPixel = 0;
                int NumBitsPerPixel = 0;
                int NumChannels = 0;

                switch (Extension)
                {
                    case "tiff":

                        loci.formats.@in.TiffReader MyTiffReader = new loci.formats.@in.TiffReader();
                        MyTiffReader.setId(CurrentName);
                        rgbValues = MyTiffReader.openBytes(0);
                        this.Width = MyTiffReader.getSizeX();
                        this.Height = MyTiffReader.getSizeY();
                        this.Depth = MyTiffReader.getSizeZ();
                        NumChannels = MyTiffReader.getSizeC();
                        //MyTiffReader.
                        NumBitsPerPixel = MyTiffReader.getBitsPerPixel();
                        break;
                    case "tif":
                        //    vtkTIFFReader TIFFReader = vtkTIFFReader.New();
                        //    TIFFReader.SetFileName(Path);
                        //    TIFFReader.Update();
                        //    vtkImageData ID0 = TIFFReader.GetOutput();

                        ////    cVolume3D Volume3D0 = new cVolume3D(ID0, new HCSAnalyzer.Classes._3D.cPoint3D(0, 0, 0));

                        //    cViewerImage3D VI3D = new cViewerImage3D();
                        //    VI3D.SetInputData(ID0);
                        //    VI3D.Run();

                        //    cDisplayToWindow DTW = new cDisplayToWindow();
                        //    DTW.SetInputData(VI3D.GetOutPut());
                        //    DTW.Run();
                        //    DTW.Display();


                        // vtkVolume vol0 = vtkVolume.New();


                        // vtkRenderer renderer0 = vtkRenderer.New();
                        // renderer0.AddVolume(Volume3D0.vtk_volume);
                        // vtkRenderWindow window0 = vtkRenderWindow.New();
                        // window0.AddRenderer(renderer0);
                        //113 vtkInteractorStyleImage imageStyle
                        //114 
                        //115 vtkRenderWindowInteractor interactor
                        //116   interactor SetInteractorStyle imageStyle
                        //117   window SetInteractor interactor
                        //  window0.Render();


                        //break;

                        loci.formats.@in.TiffReader MyTifReader = new loci.formats.@in.TiffReader();
                        MyTifReader.setId(CurrentName);
                        int ImageCount = MyTifReader.getImageCount();
                      
                        this.Width = MyTifReader.getSizeX();
                        
                        this.Height = MyTifReader.getSizeY();
                        this.Depth = MyTifReader.getSizeZ();
                        NumChannels = MyTifReader.getSizeC();
                        NumBitsPerPixel = MyTifReader.getBitsPerPixel();
                        string Order = MyTifReader.getDatasetStructureDescription();

                        if (ImageCount == 1)
                        {
                            rgbValues = MyTifReader.openBytes(0);
                        }
                        else
                        {
                            rgbValues = new byte[this.Width * this.Height * this.Depth * NumChannels * (NumBitsPerPixel / 8)];
                            int IdxImage = 0;
                            int SizeImageBlock = this.Width*this.Height*this.Depth;
                            int ImageSliceSize = this.Width*this.Height;

                            for (int Z = 0; Z < this.Depth; Z++)
                            {
                                for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
                                {
                                    byte[] TmpTable = MyTifReader.openBytes(IdxImage);

                                    Array.Copy(TmpTable, 0, rgbValues, IdxChannel * SizeImageBlock + Z * ImageSliceSize, TmpTable.Length);

                                    IdxImage++;
                                }
                            }
                            //byte[] TmpTable

                        }
                        break;
                    case "jpg":
                        vtkJPEGReader JPEGReader = vtkJPEGReader.New();
                        JPEGReader.SetFileName(CurrentName);
                        JPEGReader.Update();
                        vtkImageData ID = JPEGReader.GetOutput();


                      //  cVolumeRendering3D Volume3D = new cVolumeRendering3D(ID, new HCSAnalyzer.Classes._3D.cPoint3D(0, 0, 0));
                        // int[] Pso = new int[3];
                        // Pso[0] = 10;


                        //c3DWorld World3D = new c3DWorld(new cPoint3D(100, 100, 100), new cPoint3D(1, 1, 1), new RenderWindowControl(), Pso, null);
                        //   vtkImageReader2 MyRead = vtkImageReader2.New();
                        //   MyRead.SetFileName(Path);
                        //   MyRead.GetFileDimensionality();
                        ////   reader->SetFilePrefix(argv[1]);
                        ////   MyRead.SetDataExtent(0, 63, 0, 63, 1, 93);
                        //   MyRead.SetDataSpacing(1,1,1);
                        //   MyRead.SetDataOrigin(0.0, 0.0, 0.0);
                        //   MyRead.SetDataScalarTypeToSignedChar();
                        //   MyRead.SetDataByteOrderToLittleEndian();
                        //   MyRead.UpdateWholeExtent();

                       // vtkVolume vol = vtkVolume.New();
                        //vtkImageActor vol = vtkImageActor.New();
                        // actor.SetInput(JPEGReader.GetOutput());


                       // vtkRenderer renderer = vtkRenderer.New();
                       // renderer.AddVolume(Volume3D.vtk_volume);
                       // vtkRenderWindow window = vtkRenderWindow.New();
                       // window.AddRenderer(renderer);
                        //113 vtkInteractorStyleImage imageStyle
                        //114 
                        //115 vtkRenderWindowInteractor interactor
                        //116   interactor SetInteractorStyle imageStyle
                        //117   window SetInteractor interactor
                       // window.Render();
                       // return;
                        //MyRead.OpenFile();

                     //   break;
                        loci.formats.@in.JPEGReader MyJpegReader = new loci.formats.@in.JPEGReader();
                        MyJpegReader.setId(CurrentName);
                        rgbValues = MyJpegReader.openBytes(0);
                        this.Width = MyJpegReader.getSizeX();
                        this.Height = MyJpegReader.getSizeY();
                        this.Depth = MyJpegReader.getSizeZ();
                        NumChannels = MyJpegReader.getSizeC();
                        NumBitsPerPixel = MyJpegReader.getBitsPerPixel();
                        break;
                    case "jpeg":
                        loci.formats.@in.JPEGReader MyJpeg1Reader = new loci.formats.@in.JPEGReader();
                        MyJpeg1Reader.setId(CurrentName);
                        rgbValues = MyJpeg1Reader.openBytes(0);
                        this.Width = MyJpeg1Reader.getSizeX();
                        this.Height = MyJpeg1Reader.getSizeY();
                        this.Depth = MyJpeg1Reader.getSizeZ();
                        NumChannels = MyJpeg1Reader.getSizeC();
                        NumBitsPerPixel = MyJpeg1Reader.getBitsPerPixel();
                        break;
                    case "png":
                        loci.formats.@in.APNGReader MyPNGReader = new loci.formats.@in.APNGReader();
                        MyPNGReader.setId(CurrentName);
                        rgbValues = MyPNGReader.openBytes(0);
                        this.Width = MyPNGReader.getSizeX();
                        this.Height = MyPNGReader.getSizeY();
                        this.Depth = MyPNGReader.getSizeZ();
                        NumChannels = MyPNGReader.getSizeC();
                        NumBitsPerPixel = MyPNGReader.getBitsPerPixel();
                        break;
                    case "gif":
                        loci.formats.@in.GIFReader MyGIFReader = new loci.formats.@in.GIFReader();
                        MyGIFReader.setId(CurrentName);
                        rgbValues = MyGIFReader.openBytes(0);
                        this.Width = MyGIFReader.getSizeX();
                        this.Height = MyGIFReader.getSizeY();
                        this.Depth = MyGIFReader.getSizeZ();
                        NumChannels = MyGIFReader.getSizeC();
                        NumBitsPerPixel = MyGIFReader.getBitsPerPixel();
                        break;
                    case "bmp":
                        loci.formats.@in.BMPReader MyBMPReader = new loci.formats.@in.BMPReader();
                        MyBMPReader.setId(CurrentName);
                        rgbValues = MyBMPReader.openBytes(0);
                        this.Width = MyBMPReader.getSizeX();
                        this.Height = MyBMPReader.getSizeY();
                        this.Depth = MyBMPReader.getSizeZ();
                        NumChannels = MyBMPReader.getSizeC();
                        NumBitsPerPixel = MyBMPReader.getBitsPerPixel();
                        break;
                    default:
                        break;
                }

                if (NumBitsPerPixel == 8)
                {
                    NumBytePerPixel = 1;
                }
                else if (NumBitsPerPixel == 16)
                {
                    NumBytePerPixel = 2;
                }
                else if (NumBitsPerPixel == 24)
                {
                    NumBytePerPixel = 3;
                }
                else if (NumBitsPerPixel == 32)
                {
                    NumBytePerPixel = 4;
                }
                else
                {
                    // format not implemented
                    return;
                }

                //this.Name = Path;
                //FreeImageAPI.FIMULTIBITMAP LoadedMultiPageImage = FreeImage.OpenMultiBitmap(FREE_IMAGE_FORMAT.FIF_TIFF, Path, false, true, true, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
                //FreeImageAPI.FIBITMAP LoadedPage = FreeImage.LockPage(LoadedMultiPageImage,0);
                //FreeImageAPI.FIBITMAP LoadedImage = FreeImage.ConvertToStandardType(LoadedPage, true);
                //if (FileName == "")
                //    this.Name = Path;
                //else
                this.Name = CurrentName;

                this.SliceSize = this.Width * this.Height;
                this.ImageSize = SliceSize * Depth;

                //FreeImage.FlipVertical(LoadedImage);
                ////Image CurrentMSImage = (Image)FreeImage.GetBitmap(LoadedImage);
                //FreeImageAPI.FIBITMAP Converted24Im = FreeImage.ConvertToGreyscale(LoadedImage);
                //IntPtr Pt =  FreeImage.GetBits(LoadedImage);

                //int bytes = Width*Height*3;
                //byte[] rgbValues = new byte[bytes];

                //// Copy the RGB values into the array.
                //System.Runtime.InteropServices.Marshal.Copy(Pt, rgbValues, 0,bytes);
                //FormForImageDisplay NewDispl = new FormForImageDisplay();
                //NewDispl.pictureBoxForImage.Image = (Image)FreeImage.GetBitmap(LoadedImage);
                //NewDispl.Show();


                //  this.Data = new float[this.NumChannels][];
                if (IdxName == 0)
                    this.SingleChannelImage = new cListSingleChannelImage();

                float Value;

                //int GlobalIdx = 0;
                //cSingleChannelImage CI = new cSingleChannelImage(this.Width * this.Height * this.Depth);
                //CI.Data[0] = 10;
                for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
                    this.SingleChannelImage.Add(new cSingleChannelImage(this.Width, this.Height, this.Depth, new cPoint3D(1,1,1)));

                int PixIdx = 0;
                for (int IdxZ = 0; IdxZ < this.Depth; IdxZ++)
                    for (int IdxY = 0; IdxY < this.Height; IdxY++)
                        for (int IdxX = 0; IdxX < this.Width; IdxX++)
                        {
                            for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
                            {
                                Value = 0;
                                for (int i = 0; i < NumBytePerPixel; i++)
                                    Value += (rgbValues[NumBytePerPixel * PixIdx + i + IdxChannel * this.SliceSize * this.Depth] << (i * 8));

                                this.SingleChannelImage[IdxChannel + ChannelStart].Data[PixIdx] = Value;
                            }
                            PixIdx++;
                        }
                ChannelStart += NumChannels;
            }
            /*
            for (int IdxY = 0; IdxY < this.Height; IdxY++)
                for (int IdxX = 0; IdxX < this.Width; IdxX++)
                {
                    for (int IdxChannel = 0; IdxChannel < NumChannels; IdxChannel++)
                    {
                        this.Data[IdxChannel].Data[IdxX + IdxY * this.Width] = rgbValues[GlobalIdx++];
                    }
                }
            */
            //if (LoadedImage.IsNull) return;
            // this.NumChannels = this.SingleChannelImage.Count;


        }



        #endregion
    }




}
